package com.quanyan.assets.service.impl;

import com.quanyan.api.APIResponse;
import com.quanyan.assets.emun.AssetsErrorEnum;
import com.quanyan.assets.emun.GrantType;
import com.quanyan.assets.entity.*;
import com.quanyan.assets.entity.CouponInfoVo;
import com.quanyan.assets.entity.vo.CounponInfoRespVo;
import com.quanyan.assets.entity.vo.CouponItem;
import com.quanyan.assets.entity.vo.RespActivityCouponListVo;
import com.quanyan.assets.enums.CouponGrantType;
import com.quanyan.assets.enums.CouponStatus;
import com.quanyan.assets.mapper.*;
import com.quanyan.assets.repository.UserAssetsRepository;
import com.quanyan.assets.request.ReqCouponRefund;
import com.quanyan.assets.response.RespSimpleCoupon;
import com.quanyan.assets.service.UtilCouponService;
import com.quanyan.common.enums.BaseEnum;
import com.quanyan.common.exception.BizException;
import com.quanyan.common.utils.StringUtil;
import com.quanyan.common.utils.TimeUtils;
import com.quanyan.user.response.RespUserInfoBase;
import com.quanyan.user.serviceFacade.UserServiceFacade;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.Valid;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 *
 * Created by wmb on 2016/10/25.
 */
@Service("utilCouponService")
public class UtilCouponServiceImpl implements UtilCouponService {

    private static final Logger logger = LoggerFactory.getLogger(UtilCouponServiceImpl.class);
    private static final byte COUPON_TEMPLATE_ENABLE = 1; // 启用
    private static final byte COUPON_TEMPLATE_DISENABLE = 2; //停用

    @Autowired
    private CouponMapper couponMapper;
    @Autowired
    private ETbUserAssetsMapper eTbUserAssetsMapper;
    @Autowired
    private UserServiceFacade userServiceFacade;
    @Autowired
    private TbUserAssetsGrantHistoryMapper tbUserAssetsGrantHistoryMapper;
    @Autowired
    private UserAssetsRepository userAssetsRepository;
    @Autowired
    private TbCouponInfoMapper tbCouponInfoMapper;
    @Autowired
    private TbCouponMapper tbCouponMapper;

    @Override
    public void refundCouponSubmit(ReqCouponRefund couponRefund) {
        couponMapper.refundSubmit(couponRefund.getCouponCode());
    }

    @Override
    public void refundCouponSuccess(ReqCouponRefund couponRefund) {
        couponMapper.refundSuccess(couponRefund.getCouponCode());
    }

    @Override
    public void refundCouponFail(ReqCouponRefund couponRefund) {
        couponMapper.refundFail(couponRefund.getCouponCode());
    }

    //优惠券过期处理
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void expiredHandle() {
        Date nowTime = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(nowTime);
        calendar.add(Calendar.DATE, -1);

        //获取拥有失效卡券的用户uid
        List<TbCouponInfo> invalidCoupons = couponMapper.getInvalidCouponInfoCountInfo(calendar.getTime());
        for (TbCouponInfo invalidCoupon : invalidCoupons) {
            int coupon = couponMapper.hideInvalidCoupon(invalidCoupon.getUid(), calendar.getTime());
            //invalidCouponUid == null 的原因是可能出现用户没有认领该卡券，但过了有效期。用户卡券资产中的“可用数量”不包括“已停用的卡券”的数量
            if(!CouponStatus.DISABLE.id.toString().equals(invalidCoupon.getStatus().toString()) && invalidCoupon.getUid() != null && coupon > 0) {
                int size = eTbUserAssetsMapper.updateUseableAmount(invalidCoupon.getUid(), coupon);
                if(size <= 0){
                    //
                }
            }
        }
    }

    @Override
    @Valid
    @Transactional(rollbackFor = Exception.class)
    public APIResponse<BaseEnum> grantCoupons(Integer uid) throws ParseException {
        grantCouponsValid(uid);
        String startDateStr = "2016-11-10 00:00:00";
        String endDateStr = "2016-11-30 59:59:59";
        //派发优惠券
        List<String> couponIds = Arrays.asList("CH161107153715", "CH161107154715", "CH161107155159", "CH161107155503", "CH161107155638");//礼包盒
        byte grantType = GrantType.NEWCOMER.getId();
        doGrantCoupons(uid, startDateStr, endDateStr, couponIds, grantType);
        return APIResponse.returnSuccess();
    }

    @Override
    @Valid
    @Transactional(rollbackFor = Exception.class)
    public APIResponse<BaseEnum> grantCoupons2(Integer uid) throws ParseException {
        grantCouponsValid(uid);
        String startDateStr = "2016-11-14 00:00:00";
//        String startDateStr = "2016-11-10 00:00:00";
        String endDateStr = "2016-11-27 59:59:59";
        //派发优惠券
        List<String> couponIds = Arrays.asList("CH161111140257", "CH161111140257");//礼包盒
        byte grantType = GrantType.NEWCOMER2.getId();
        doGrantCoupons(uid, startDateStr, endDateStr, couponIds, grantType);
        return APIResponse.returnSuccess();
    }

    @Override
    @Transactional
    public APIResponse<CouponInfoVo> obtainCoupons(String couponTemplateCode, Integer uid) {
        // 合法性校验
        TbCoupon tbCoupon = this.getTbCouponByTemplateCode(couponTemplateCode);
        if (tbCoupon == null) {
            throw new BizException(AssetsErrorEnum.COUPON_TEMPLATE_NOT_EXISTS);
        }
        if (tbCoupon.getStatus() != this.COUPON_TEMPLATE_ENABLE) {
            throw new BizException(AssetsErrorEnum.COUPON_TEMPLATE_DISABLE);
        }
        if (tbCoupon.getDeadline() != null && tbCoupon.getDeadline().getTime() - new Date().getTime() < 0) {//已过截止日期
            throw new BizException(AssetsErrorEnum.NOT_IN_THE_ACTIVITY, "领取时间已过。");
        }
        if (tbCoupon.getMaxNum() != -1) {
            if (tbCoupon.getMaxNum() - tbCoupon.getReceiveNum() <= 0) {
                throw new BizException(AssetsErrorEnum.COUPON_IS_NONE);
            }
        }

        // 校验发放次数限制
        Byte limitType = tbCoupon.getLimitType();
        Integer limitNum = tbCoupon.getLimitNum();
        verifyGrantNum(limitType, limitNum, couponTemplateCode, uid);

        // 赋值
        TbCouponInfo couponInfo = new TbCouponInfo();
        couponInfo.setCouponType(tbCoupon.getCouponType());
        couponInfo.setDiscount(tbCoupon.getDiscount());
        couponInfo.setTopDiscountAmount(tbCoupon.getTopDiscountAmount());
        couponInfo.setStatus(Byte.valueOf(CouponStatus.RECEIVE.getId().toString()));
        couponInfo.setCity(tbCoupon.getCity());
        couponInfo.setSportType(tbCoupon.getSportType());
        couponInfo.setOrderType(tbCoupon.getOrderType());
        couponInfo.setCouponAmount(couponInfo.getCouponAmount());
        couponInfo.setCouponCode(TimeUtils.dateToEngString(new Date(), "yy") + StringUtil.genRandomCode(10, false).toUpperCase());
        couponInfo.setCouponId(tbCoupon.getCouponId());
        couponInfo.setCouponName(tbCoupon.getCouponName());
        couponInfo.setCouponType(tbCoupon.getCouponType());
        couponInfo.setEnabledAmount(tbCoupon.getEnabledAmount());
        couponInfo.setCouponAmount(tbCoupon.getCouponAmount());
        couponInfo.setUid(uid);
        couponInfo.setIsShow(tbCoupon.getIsShow());
        couponInfo.setPaymethod(tbCoupon.getPaymethod());
        couponInfo.setPlaceIds(tbCoupon.getPlaceIds());
        couponInfo.setReceiveType(CouponGrantType.USER_RECEIVE.getId());
        couponInfo.setLimitWeekday(tbCoupon.getLimitWeekday());
        couponInfo.setLimitTime(tbCoupon.getLimitTime());
        APIResponse<RespUserInfoBase> respUserInfoBaseAPIResponse = userServiceFacade.queryUserInfo(uid);
        if (respUserInfoBaseAPIResponse != null && respUserInfoBaseAPIResponse.isRet()) {
            couponInfo.setUserMobile(respUserInfoBaseAPIResponse.getData().getMobile());
        }
        couponInfo.setCreateTime(new Date());
        couponInfo.setReceiveTime(new Date());
        String validBeginDate = tbCoupon.getValidBeginDate();
        String validEndDate = tbCoupon.getValidEndDate();
        if (tbCoupon.getDatetype() == 2) { //固定时长
            Date now = new Date();
            validBeginDate = TimeUtils.dateToEngString(now, "yyyy-MM-dd");
            validEndDate = TimeUtils.dateToEngString(TimeUtils.getDateAfterDate(now, tbCoupon.getValidDays()), "yyyy-MM-dd");
        }
        couponInfo.setValidBeginDate(validBeginDate);
        couponInfo.setValidEndDate(validEndDate);

        // 插入更新
        tbCouponInfoMapper.insert(couponInfo);
        couponMapper.updateReciveNum(tbCoupon.getId());
        // 防止并发超卖
        if (tbCoupon.getMaxNum() != -1) {
            TbCoupon tc = this.getTbCouponByTemplateCode(couponTemplateCode);
            if (tc.getMaxNum() - tc.getReceiveNum() < 0) {
                throw new BizException(AssetsErrorEnum.COUPON_IS_NONE);
            }
        }

        CouponInfoVo couponInfoVo = new CouponInfoVo();
        couponInfoVo.setCouponCode(couponInfo.getCouponCode());
        couponInfoVo.setValidEndDate(validEndDate);
        couponInfoVo.setValidBeginDate(validBeginDate);
        return APIResponse.returnSuccess(couponInfoVo);
    }

    private void verifyGrantNum(Byte limitType, Integer limitNum, String couponTemplateCode, int uid) {
        if (limitType == null) {
            limitType = 1;
        }
        if (limitNum == null) {
            limitNum = 1;
        }
        if (limitNum != -1) { // 无限
            if (limitType == 1) {
                List<TbCouponInfo> couponInfos = this.findTbCouponInfo(couponTemplateCode, uid, CouponGrantType.USER_RECEIVE.getId());
                if (couponInfos.size() >= limitNum) {
                    throw new BizException(AssetsErrorEnum.NOT_GRANT_AGAIN);
                }
            } else if (limitType == 2) { // 每天
                String nowDateStr = TimeUtils.getSimpleDateEngString(new Date());
                Date receiveTimeStart = TimeUtils.engStringToDate(nowDateStr + " 00:00:00", TimeUtils.DF_PATTERN_YYYY_MM_DD_HH_MM_SS);
                Date receiveTimeEnd = TimeUtils.engStringToDate(nowDateStr + " 23:59:59", TimeUtils.DF_PATTERN_YYYY_MM_DD_HH_MM_SS);
                List<TbCouponInfo> couponInfos = this.findTbCouponInfo(couponTemplateCode, uid, CouponGrantType.USER_RECEIVE.getId(), receiveTimeStart, receiveTimeEnd);
                if (couponInfos.size() >= limitNum) {
                    throw new BizException(AssetsErrorEnum.NOT_GRANT_AGAIN);
                }
            }
        }
    }

    @Override
    @Transactional
    public APIResponse<CouponInfoVo> obtainCouponsByCouponCode(String couponCode, Integer uid) {
        // 合法性校验
        TbCouponInfo tbCouponInfo = this.getTbCouponInfoByCode(couponCode);
        if (tbCouponInfo == null) {
            throw new BizException(AssetsErrorEnum.COUPON_CODE_NOT_EXISTS);
        }
        if (tbCouponInfo.getUid() != null) {
            if (tbCouponInfo.getUid().equals(uid)) {
                throw new BizException(AssetsErrorEnum.ALREADY_GRANT_YOU);
            } else {
                throw new BizException(AssetsErrorEnum.ALREADY_GRANT_OTHER);
            }
        }

        TbCoupon tbCoupon = this.getTbCouponByTemplateCode(tbCouponInfo.getCouponId());
        if (tbCoupon.getStatus() != this.COUPON_TEMPLATE_ENABLE) {
            throw new BizException(AssetsErrorEnum.COUPON_TEMPLATE_DISABLE);
        }
        if (tbCoupon.getDeadline() != null && tbCoupon.getDeadline().getTime() - new Date().getTime() < 0) {//已过截止日期
            throw new BizException(AssetsErrorEnum.NOT_IN_THE_ACTIVITY, "领取时间已过。");
        }

        // 校验发放次数限制
        Byte limitType = tbCoupon.getLimitType();
        Integer limitNum = tbCoupon.getLimitNum();
        verifyGrantNum(limitType, limitNum, tbCoupon.getCouponId(), uid);

        // 赋值
        tbCouponInfo.setStatus(Byte.valueOf(CouponStatus.RECEIVE.getId().toString()));
        tbCouponInfo.setReceiveType(CouponGrantType.USER_RECEIVE.getId());
        tbCouponInfo.setUid(uid);
        APIResponse<RespUserInfoBase> respUserInfoBaseAPIResponse = userServiceFacade.queryUserInfo(uid);
        if (respUserInfoBaseAPIResponse != null && respUserInfoBaseAPIResponse.isRet()) {
            tbCouponInfo.setUserMobile(respUserInfoBaseAPIResponse.getData().getMobile());
        }
        tbCouponInfo.setReceiveTime(new Date());
        String validBeginDate = tbCoupon.getValidBeginDate();
        String validEndDate = tbCoupon.getValidEndDate();
        if (tbCoupon.getDatetype() == 2) { //固定时长
            Date now = new Date();
            validBeginDate = TimeUtils.dateToEngString(now, "yyyy-MM-dd");
            validEndDate = TimeUtils.dateToEngString(TimeUtils.getDateAfterDate(now, tbCoupon.getValidDays()), "yyyy-MM-dd");
        }
        tbCouponInfo.setValidBeginDate(validBeginDate);
        tbCouponInfo.setValidEndDate(validEndDate);

        // 乐观锁，更新
        TbCouponInfoExample example = new TbCouponInfoExample();
        TbCouponInfoExample.Criteria criteria = example.createCriteria();
        criteria.andIdEqualTo(tbCouponInfo.getId());
        criteria.andUidIsNull();
        int count = tbCouponInfoMapper.updateByExample(tbCouponInfo, example);
        if (count <= 0) {
            TbCouponInfo info = this.getTbCouponInfoByCode(couponCode);
            if (info.getUid() != null) {
                if (info.getUid().equals(uid)) {
                    throw new BizException(AssetsErrorEnum.ALREADY_GRANT_YOU);
                } else {
                    throw new BizException(AssetsErrorEnum.ALREADY_GRANT_OTHER);
                }
            }
        }
        couponMapper.updateReciveNum(tbCoupon.getId());

        CouponInfoVo couponInfoVo = new CouponInfoVo();
        couponInfoVo.setCouponCode(tbCouponInfo.getCouponCode());
        couponInfoVo.setValidEndDate(tbCouponInfo.getValidEndDate());
        couponInfoVo.setValidBeginDate(tbCouponInfo.getValidBeginDate());
        return APIResponse.returnSuccess(couponInfoVo);
    }

    @Override
    public APIResponse<CounponInfoRespVo> getCouponInfo(String couponCode) {
        CounponInfoRespVo respVo = new CounponInfoRespVo();
        // 合法性校验
        TbCouponInfo tbCouponInfo = this.getTbCouponInfoByCode(couponCode);

        if (tbCouponInfo == null) {
            respVo.setStatus(0); // 不存在该优惠券码
            return APIResponse.returnSuccess(respVo);
        }
        respVo.setCouponAmount(tbCouponInfo.getCouponAmount());
        respVo.setCouponCode(tbCouponInfo.getCouponCode());
        respVo.setCouponName(tbCouponInfo.getCouponName());
        respVo.setCouponType(tbCouponInfo.getCouponType());
        respVo.setDiscount(tbCouponInfo.getDiscount());
        respVo.setTopDiscountAmount(tbCouponInfo.getTopDiscountAmount());
        respVo.setEnabledAmount(tbCouponInfo.getEnabledAmount());

        String validBeginDate = tbCouponInfo.getValidBeginDate();
        String validEndDate = tbCouponInfo.getValidEndDate();
        if (StringUtil.isBlankOrNull(validBeginDate) || StringUtil.isBlankOrNull(validEndDate)) {
            TbCoupon tbCoupon = this.getTbCouponByTemplateCode(tbCouponInfo.getCouponId());
            if (tbCoupon.getDatetype() == 2) { //固定时长
                Date now = new Date();
                validBeginDate = TimeUtils.dateToEngString(now, "yyyy-MM-dd");
                validEndDate = TimeUtils.dateToEngString(TimeUtils.getDateAfterDate(now, tbCoupon.getValidDays()), "yyyy-MM-dd");
            }
        }

        respVo.setValidBeginDate(validBeginDate);
        respVo.setValidEndDate(validEndDate);
        if (tbCouponInfo.getUid() != null) {
            respVo.setStatus(1); // 已被领取（该优惠券码已经被人领取了）
        } else {
            respVo.setStatus(2); // 待领取
        }

        return APIResponse.returnSuccess(respVo);
    }

    @Override
    public TbCoupon getTbCouponByTemplateCode(String couponTemplateCode) {
        TbCouponExample example = new TbCouponExample();
        TbCouponExample.Criteria criteria = example.createCriteria();
        criteria.andCouponIdEqualTo(couponTemplateCode);

        List<TbCoupon> coupons = tbCouponMapper.selectByExample(example);
        if (coupons.size() >= 1) {
            return coupons.get(0);
        }
        return null;
    }

    @Override
    public TbCouponInfo getTbCouponInfoByCode(String couponCode) {
        TbCouponInfoExample example = new TbCouponInfoExample();
        TbCouponInfoExample.Criteria criteria = example.createCriteria();
        criteria.andCouponCodeEqualTo(couponCode);

        List<TbCouponInfo> coupons = tbCouponInfoMapper.selectByExample(example);
        if (coupons.size() >= 1) {
            return coupons.get(0);
        }
        return null;
    }

    @Override
    public List<TbCouponInfo> findTbCouponInfo(String couponTemplateCode, int uid, byte couponGrantTpe) {
        TbCouponInfoExample example = new TbCouponInfoExample();
        TbCouponInfoExample.Criteria criteria = example.createCriteria();
        criteria.andCouponIdEqualTo(couponTemplateCode);
        criteria.andUidEqualTo(uid);
        criteria.andReceiveTypeEqualTo(couponGrantTpe);
        return tbCouponInfoMapper.selectByExample(example);
    }

    @Override
    public List<TbCouponInfo> findTbCouponInfo(List<String> couponTemplateCodes, int uid, byte couponGrantTpe) {
        if (couponTemplateCodes.size() <= 0) {
            return new ArrayList<>();
        }
        TbCouponInfoExample example = new TbCouponInfoExample();
        TbCouponInfoExample.Criteria criteria = example.createCriteria();
        criteria.andCouponIdIn(couponTemplateCodes);
        criteria.andUidEqualTo(uid);
        criteria.andReceiveTypeEqualTo(couponGrantTpe);
        return tbCouponInfoMapper.selectByExample(example);
    }

    @Override
    public List<TbCouponInfo> findTbCouponInfo(List<String> couponTemplateCodes, int uid, byte couponGrantTpe, Date receiveTimeStart, Date receiveTimeEnd) {
        TbCouponInfoExample example = new TbCouponInfoExample();
        TbCouponInfoExample.Criteria criteria = example.createCriteria();
        criteria.andCouponIdIn(couponTemplateCodes);
        criteria.andUidEqualTo(uid);
        criteria.andReceiveTypeEqualTo(couponGrantTpe);
        criteria.andReceiveTimeGreaterThan(receiveTimeStart);
        criteria.andReceiveTimeLessThan(receiveTimeEnd);
        return tbCouponInfoMapper.selectByExample(example);
    }

    @Override
    public List<TbCouponInfo> findTbCouponInfo(String couponTemplateCode, int uid, byte couponGrantTpe, Date receiveTimeStart, Date receiveTimeEnd) {
        TbCouponInfoExample example = new TbCouponInfoExample();
        TbCouponInfoExample.Criteria criteria = example.createCriteria();
        criteria.andCouponIdEqualTo(couponTemplateCode);
        criteria.andUidEqualTo(uid);
        criteria.andReceiveTypeEqualTo(couponGrantTpe);
        criteria.andReceiveTimeGreaterThan(receiveTimeStart);
        criteria.andReceiveTimeLessThan(receiveTimeEnd);
        return tbCouponInfoMapper.selectByExample(example);
    }

    @Override
    public APIResponse<RespActivityCouponListVo> getActivityCouponList(Byte activityType, Integer uid) {
        logger.info("activityType:"+activityType+"uid:"+uid);
        boolean canObtain = true;
        RespActivityCouponListVo respActivityCouponListVo = new RespActivityCouponListVo();
        List<CouponItem> couponItems = couponMapper.getActivityCouponList(activityType);
        List<String> couponTemplateCodes = new ArrayList<>();
        for (CouponItem item : couponItems) {
            couponTemplateCodes.add(item.getCouponTemplateCode());
        }
        if (uid != null && uid != 0) { // 已经登录
            List<TbCouponInfo> tbCouponInfoList = new ArrayList<>();
            if (activityType == 2) { //领券中心
                String nowDateStr = TimeUtils.getSimpleDateEngString(new Date());
                Date receiveTimeStart = TimeUtils.engStringToDate(nowDateStr + " 00:00:00", TimeUtils.DF_PATTERN_YYYY_MM_DD_HH_MM_SS);
                Date receiveTimeEnd = TimeUtils.engStringToDate(nowDateStr + " 23:59:59", TimeUtils.DF_PATTERN_YYYY_MM_DD_HH_MM_SS);
                tbCouponInfoList = this.findTbCouponInfo(couponTemplateCodes, uid, CouponGrantType.USER_RECEIVE.getId(), receiveTimeStart, receiveTimeEnd);
            } else if (activityType == 3) { // 新人红包
                tbCouponInfoList = this.findTbCouponInfo(couponTemplateCodes, uid, CouponGrantType.USER_RECEIVE.getId());
            } else if (activityType == 4) { // 双蛋活动
                tbCouponInfoList = this.findTbCouponInfo(couponTemplateCodes, uid, CouponGrantType.USER_RECEIVE.getId());
            } else { // 默认
                tbCouponInfoList = this.findTbCouponInfo(couponTemplateCodes, uid, CouponGrantType.USER_RECEIVE.getId());
            }
            if (tbCouponInfoList.size() > 0) {
                canObtain = false;
            }
            for (CouponItem item : couponItems) {
                item.setObtain(false);
                for (TbCouponInfo tbCouponInfo : tbCouponInfoList) {
                    if (item.getCouponTemplateCode().equals(tbCouponInfo.getCouponId())) {
                        item.setObtain(true);
                        break;
                    }
                }
            }
        } else { // 没有登录默认都是false
            for (CouponItem item : couponItems) {
                item.setObtain(false);
            }
        }
        respActivityCouponListVo.setCouponList(couponItems);
        respActivityCouponListVo.setCanObtain(canObtain);
        return APIResponse.returnSuccess(respActivityCouponListVo);
    }

    private void doGrantCoupons(Integer uid, String startDateStr, String endDateStr, List<String> couponIds, byte grantType) throws ParseException {
        //是否在活动时间内
        SimpleDateFormat startDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat endDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date nowTime = new Date();
        if(nowTime.getTime() < startDate.parse(startDateStr).getTime() || nowTime.getTime() > endDate.parse(endDateStr).getTime()){
            throw new BizException(AssetsErrorEnum.NOT_IN_THE_ACTIVITY);
        }
        //校验是否重复领取
        try {
            TbUserAssetsGrantHistory history = new TbUserAssetsGrantHistory();
            history.setUid(uid);
            history.setCreateTime(new Date());
            history.setGrantType(grantType);
            tbUserAssetsGrantHistoryMapper.insert(history);
        } catch (DuplicateKeyException e){//当发生重复领取时
            throw new BizException(AssetsErrorEnum.NOT_GRANT_AGAIN);
        }
        APIResponse<RespUserInfoBase> respUserInfoBaseAPIResponse = userServiceFacade.queryUserInfo(uid);
        RespUserInfoBase data = respUserInfoBaseAPIResponse.getData();
        if(respUserInfoBaseAPIResponse.isRet() && data != null){
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            for (String couponId : couponIds) {
                RespSimpleCoupon coupon = couponMapper.getCoupon(couponId);
                String validBeginDate = null;
                String validEndDate = null;
                if (coupon.getDateType() == 2) {
                    validBeginDate = simpleDateFormat.format(nowTime);
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(simpleDateFormat.parse(validBeginDate));
                    calendar.add(Calendar.DATE, coupon.getValidDays());
                    validEndDate = simpleDateFormat.format(calendar.getTime());
                } else {
                    validBeginDate = coupon.getValidBeginDate();
                    validEndDate = coupon.getValidEndDate();
                }
                int trys = 3;//重试次数
                int rows = 0;
                for (int i = 1; i <= trys; i++) {
                    try {
                        rows = couponMapper.grantCouponTopOne(couponId, uid, data.getMobile(), validBeginDate, validEndDate);
                        break;
                    } catch (Exception e){
                        if(trys == i){
                            logger.error("用户 {} 获取优惠券失败", uid, e);
                        }
                    }
                }
                if (rows <= 0) {//优惠券已经送完
                    throw new BizException(AssetsErrorEnum.COUPONS_IS_USE_END);
                }
            }
            int rows = eTbUserAssetsMapper.updateAddUseableAmount(uid, couponIds.size());//更新资产信息优惠券的可用数量
            if(rows <= 0){
                userAssetsRepository.initAllCount(uid);
                eTbUserAssetsMapper.updateAddUseableAmount(uid, couponIds.size());//更新资产信息优惠券的可用数量 again
            }
        } else {
            throw new BizException(AssetsErrorEnum.USER_INFO_NOT_EXISTS);
        }
    }

    private void grantCouponsValid(Integer uid){
        if(null == uid){
            throw new BizException(AssetsErrorEnum.USER_ID_NULL);
        }
    }

}
